package engine;

import java.util.Iterator;
import java.util.Vector;
import com.jamonapi.*;

import org.apache.log4j.Logger;

import sun.misc.Perf.GetPerfAction;

public class Chessboard implements Constants {

	// ***
	// Variables used to describe the position
	// ***
	
	// the board will hold indexes to the pieces in the piece vectors below
	// black pieces will have a negative index value on the board
	public int[] boardArray; 		// Represents the 0x88 board
	public Vector whitePieces;	// shortcut Vector to hold all white pieces
	public Vector blackPieces;	// shortcut Vector to hold all black pieces
	
	public int toMove; 			// Side to move on the board

	public int enPassant;  		// Index on boardArray where en passant is
						// available, -1 if none

	public int white_castle;		// White's ability to castle
	public int black_castle; 		// Black's ability to castle
	public boolean whiteCastleStatus;
	public boolean blackCastleStatus;
	
	public int gamePhase;

	public int movesFifty;			// Keeps track of half-moves since last capture
						// or pawn move
						
	public int movesFull; 			// Keeps track of total full moves in the game

	final static String className = Chessboard.class.getName();
	final static Logger LOG = Logger.getLogger(className);
	//END Variables

	/**
	 *  Creates an empty board
	 *
	 *  @return An empty Board
	 */
	public void ChessBoard()
	{
		this.boardArray = new int[128];
		this.toMove = 1; // White to move
		this.enPassant = -1; // No en passants available
		this.white_castle = CASTLE_NONE;
		this.black_castle = CASTLE_NONE;
		this.blackCastleStatus = false;
		this.whiteCastleStatus = false;
	}
	// END Board()
	
	/**
	 *  Sets the board to the starting position
	 *  rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1
	 */
	public void setupBoard()
	{
		inputFEN("rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1");
	}
	// END setupStart()

	/**
	 *  Makes a Move on the board
	 *
	 *  @param Move move
	 */
	public void makeMove(Move move)
	{
		
		
		
		Monitor mon = MonitorFactory.start("realMakeMove");
		LOG.debug("Entering makeMove");
		//LOG.debug("Move Info: " + move.moveType + ", " + move.pieceMoving + ", "  + move.fromIndex + ", " + move.toIndex);
		//LOG.debug(getFEN());
		
		
		
		Vector attackers = getAttackingPieces();
		Vector defenders = getDefendingPieces();
		
		Piece movingPiece = getPieceFromArray(boardArray[move.fromIndex], attackers);
		Piece capturedPiece = null;
		
		enPassant = -1; // Set the en passant square to none, will be reset below if it becomes available

		toMove *= -1; // Switch side to move (multiply toMove by -1 simply switches from negative to positive
		// and vice versa)

		if(move.pieceMoving != WHITE_PAWN && move.pieceMoving != BLACK_PAWN && move.capture == 0)
			movesFifty++; // Increment the moves fifty if not a pawn moving or a capture
		else
			movesFifty = 0; // If a pawned moved or it was a capture, reset the movesFifty count

		if(move.pieceMoving < 0)
			movesFull++; // Increment the total of full moves if the moving piece is black

		// Now find out what kind of move it is and act accordingly
		switch(move.moveType)
		{
			case NORMAL_MOVE:
			{
		
				// update the location of the moving piece in the piece array
				movingPiece.piece_location = move.toIndex;
				
				//  if we are capturing a piece, record it for undo and take it off the board
				if (boardArray[move.toIndex] != EMPTY_SQUARE){
					capturedPiece = getPieceFromArray(boardArray[move.toIndex], defenders);
					capturedPiece.piece_location = OFF_BOARD;
					move.capturedPieceIndex = boardArray[move.toIndex]; 
				}
								
				// move the piece to the new location on the board
				boardArray[move.toIndex] = boardArray[move.fromIndex];
				boardArray[move.fromIndex] = EMPTY_SQUARE; // Clear the original square
				


				// Check for en passant
				// If the piece moving is a white or black pawn, and it has moved
				// 2 squares (the Math.abs line checks that)
				// set the en passant square to the right index and exit the move
				if((move.pieceMoving == WHITE_PAWN || move.pieceMoving == BLACK_PAWN)
						&& Math.abs(move.toIndex - move.fromIndex) == 32)
				{
					enPassant = move.fromIndex + (move.toIndex - move.fromIndex)/2;
					break;
				}
				
				break;
			}

			case SHORT_CASTLE:
			{
				
				if (move.pieceMoving == WHITE_KING) // White king castles short
				{
					whiteCastleStatus = true;
					// get the king
					movingPiece = getPieceFromArray(boardArray[4], attackers);
					movingPiece.piece_location = 6;   // set king to castled location
					boardArray[6] = boardArray[4];   // move the array index value over
					boardArray[4] = EMPTY_SQUARE; // Empty the king square
					
					//	 get the rook
					movingPiece = getPieceFromArray(boardArray[7], attackers);
					movingPiece.piece_location = 5;   // set rook to castled location
					boardArray[5] = boardArray[7];   // move the array index value over
					boardArray[7] = EMPTY_SQUARE; // Empty the rook square

					white_castle = CASTLE_NONE; // Make further castling impossible for white
				}
				if (move.pieceMoving == BLACK_KING) // Black king castles short
				{
					blackCastleStatus = true;
					//	 get the king
					movingPiece = getPieceFromArray(boardArray[116], attackers);
					movingPiece.piece_location = 118;   // set king to castled location
					boardArray[118] = boardArray[116];   // move the array index value over
					boardArray[116] = EMPTY_SQUARE; // Empty the king square
					
					//	 get the rook
					movingPiece = getPieceFromArray(boardArray[119], attackers);
					movingPiece.piece_location = 117;   // set rook to castled location
					boardArray[117] = boardArray[119];   // move the array index value over
					boardArray[119] = EMPTY_SQUARE; // Empty the rook square
										
					black_castle = CASTLE_NONE; // Make further castling impossible for black
				}				
				break;
			}

			case LONG_CASTLE:
			{
				if (move.pieceMoving == WHITE_KING) // White king castles long
				{
					whiteCastleStatus = true;
					//	 get the king
					movingPiece = getPieceFromArray(boardArray[4], attackers);
					movingPiece.piece_location = 2;   // set king to castled location
					boardArray[2] = boardArray[4];   // move the array index value over
					boardArray[4] = EMPTY_SQUARE; // Empty the king square
					
					//	 get the rook
					movingPiece = getPieceFromArray(boardArray[0], attackers);
					movingPiece.piece_location = 3;   // set rook to castled location
					boardArray[3] = boardArray[0];   // move the array index value over
					boardArray[0] = EMPTY_SQUARE; // Empty the rook square
					
					white_castle = CASTLE_NONE; // Make further castling impossible for white
				}
				if (move.pieceMoving == BLACK_KING) // Black king castles lon
				{
					blackCastleStatus = true;
					// 	get the king
					movingPiece = getPieceFromArray(boardArray[116], attackers);
					movingPiece.piece_location = 114;   // set king to castled location
					boardArray[114] = boardArray[116];   // move the array index value over
					boardArray[116] = EMPTY_SQUARE; // Empty the king square
					
					//	 get the rook
					movingPiece = getPieceFromArray(boardArray[112], attackers);
					movingPiece.piece_location = 115;   // set rook to castled location
					boardArray[115] = boardArray[112];   // move the array index value over
					boardArray[112] = EMPTY_SQUARE; // Empty the rook square
					black_castle = CASTLE_NONE; // Make further castling impossible for black
				}		
				break;
			}

			case EN_PASSANT:
			{
				
				movingPiece.piece_location = move.toIndex;
				
				// move the pawn to the new square and clear old square
				boardArray[move.toIndex] = boardArray[move.fromIndex];
				boardArray[move.fromIndex] = EMPTY_SQUARE; // Clear the original square
				


				// Since it's an en passant capture we also need to remove the captured pawn
				// which resides one square up/down from the target square
				// If it's a white pawn capturing, clear the square below it
				if(move.pieceMoving == WHITE_PAWN){
					capturedPiece = getPieceFromArray(boardArray[move.toIndex-16], defenders);
					capturedPiece.piece_location = OFF_BOARD;
					move.capturedPieceIndex = boardArray[move.toIndex-16];
					boardArray[move.toIndex - 16] = EMPTY_SQUARE;
				}
				
				// If it wasn't a white pawn, it's a black pawn and we clear the square above it
				else{
					capturedPiece = getPieceFromArray(boardArray[move.toIndex+16], defenders);
					capturedPiece.piece_location = OFF_BOARD;
					move.capturedPieceIndex = boardArray[move.toIndex+16];
					boardArray[move.toIndex + 16] = EMPTY_SQUARE;				
				}

				break;
			}

			default: // Catches promotions since that's the only type of move left
			{
				
				
				
				movingPiece.piece_location=move.toIndex;
				// see if it is both a promotion and a capture and remove captured piece
				//
				if(boardArray[move.toIndex] != EMPTY_SQUARE){
					capturedPiece = getPieceFromArray(boardArray[move.toIndex], defenders);
					capturedPiece.piece_location = OFF_BOARD;
					move.capturedPieceIndex = boardArray[move.toIndex];
				}
				// Check for queen, rook, bishop and knight promotions
				boardArray[move.toIndex] = boardArray[move.fromIndex];
				
				boardArray[move.fromIndex] = EMPTY_SQUARE; // Empty the square it moved from
				switch(move.moveType)
				{
					// Put a promoted piece of the right color on the target square
					// We use the toMove property to get the right color but since
					// we already changed side to move we need the opposite color
					// 
					// E.g. promotion to queen and white to move would result in
					// 2*(-(-1)) = 2 and for black 2*(-(1)) = -2
					case PROMOTION_QUEEN: 
						{
							
							movingPiece.piece_type = WHITE_QUEEN*(-toMove);
							break;
						}
					case PROMOTION_ROOK: movingPiece.piece_type = WHITE_ROOK*(-toMove); break;
					case PROMOTION_BISHOP: movingPiece.piece_type = WHITE_BISHOP*(-toMove); break;
					case PROMOTION_KNIGHT: movingPiece.piece_type = WHITE_KNIGHT*(-toMove); break;
				}
								
			}
		}
		
		// We now check for castling right changes, some of them are handles above, but
		// we need to catch them for both pawn promotions and ordinary moves, so we
		// have it outside the switch.

		// If neither white nor black can castle, we don't need to check for castling changes
		// and can skip the checks
		if(white_castle != CASTLE_NONE || black_castle != CASTLE_NONE)
		{
			// If any of the key castling squares is either empty or occupied by another color
			// we revoke castling rights
		
			if(boardArray[4] <= EMPTY_SQUARE) // White king missing from 'e1'
				white_castle = CASTLE_NONE; // Remove all castling rights for white
			if(boardArray[116] >= EMPTY_SQUARE)// Black king missing from 'e8'
				black_castle = CASTLE_NONE; // Remove all castling rights for black
			
		
			if(boardArray[0] <= EMPTY_SQUARE) // White rook missing from 'a1'
			{
				if(white_castle == CASTLE_BOTH) // Remove the ability to castle long
					white_castle = CASTLE_SHORT;
				else if(white_castle == CASTLE_LONG)
					white_castle = CASTLE_NONE;
			}
		
			if(boardArray[7] <= EMPTY_SQUARE) // White rook missing from 'h1'
			{
				if(white_castle == CASTLE_BOTH) // Remove the ability to castle short
					white_castle = CASTLE_LONG;
				else if(white_castle == CASTLE_SHORT)
					white_castle = CASTLE_NONE;
			}
		
			if(boardArray[112] >= EMPTY_SQUARE) // Black rook missing from 'a8'
			{
				if(black_castle == CASTLE_BOTH) // Remove the ability to castle long
					black_castle = CASTLE_SHORT;
				else if(black_castle == CASTLE_LONG) 
					black_castle = CASTLE_NONE;
			}
		
			if(boardArray[119] >= EMPTY_SQUARE) // White rook missing from 'h1'
			{
				
				if(black_castle == CASTLE_BOTH) // Remove the ability to castle short
					black_castle = CASTLE_LONG;
				else if(black_castle == CASTLE_SHORT)
					black_castle = CASTLE_NONE;
			}
		
		}
		
		//LOG.debug(getFEN());
		LOG.debug("Exiting makeMove");
		mon.stop();
		
		
		
		//LOG.info(mon.toString());
	}
	// END makeMove()
	
	/**
	 *  Unmakes a Move on the board
	 *
	 *  @param Move move
	 */
	public void unmakeMove(Move move)
	{

		//LOG.debug("Move Info: " + move.moveType + ", " + move.pieceMoving + ", "  + move.fromIndex + ", " + move.toIndex);
		int loc = ((Piece)blackPieces.get(0)).piece_location;
		
		
		
		// Reset known variables
		enPassant = move.prevPos[0];
		white_castle = move.prevPos[1];
		black_castle = move.prevPos[2];
		movesFifty = move.prevPos[3];

		toMove *= -1; // Switch side to move back

		Vector attackers = getAttackingPieces();  // get the group who is responsible for the move
		Vector defenders = getDefendingPieces();
		Piece movingPiece = null;
		Piece capturedPiece = null;
		
		
		// If the move we're taking back was a black piece moving
		// decrement the movesFull.
		if(move.pieceMoving < 0)
			movesFull--;

		switch(move.moveType)
		{
			case SHORT_CASTLE:
				{
					if (move.pieceMoving == WHITE_KING) // White king castles short
					{
						whiteCastleStatus = false;
						// get the king
						movingPiece = getPieceFromArray(boardArray[6], attackers);
						movingPiece.piece_location = 4;   // set king to castled location
						boardArray[4] = boardArray[6];   // move the array index value over
						boardArray[6] = EMPTY_SQUARE; // Empty the king square
						
						//	 get the rook
						movingPiece = getPieceFromArray(boardArray[5], attackers);
						movingPiece.piece_location = 7;   // set rook to castled location
						boardArray[7] = boardArray[5];   // move the array index value over
						boardArray[5] = EMPTY_SQUARE; // Empty the rook square
						
					}
					if (move.pieceMoving == BLACK_KING) // Black king castles short
					{
						blackCastleStatus = false;
						// 	get the king
						movingPiece = getPieceFromArray(boardArray[118], attackers);
						movingPiece.piece_location = 116;   // set king to castled location
						boardArray[116] = boardArray[118];   // move the array index value over
						boardArray[118] = EMPTY_SQUARE; // Empty the king square
						
						//	 get the rook
						movingPiece = getPieceFromArray(boardArray[117], attackers);
						movingPiece.piece_location = 119;   // set rook to castled location
						boardArray[119] = boardArray[117];   // move the array index value over
						boardArray[117] = EMPTY_SQUARE; // Empty the rook square
					}				
					break; // Done with unmake
				}

			case LONG_CASTLE:
				{
					if (move.pieceMoving == WHITE_KING) // White king castles long
					{
						whiteCastleStatus = false;
						//	 get the king
						movingPiece = getPieceFromArray(boardArray[2], attackers);
						movingPiece.piece_location = 4;   // set king to castled location
						boardArray[4] = boardArray[2];   // move the array index value over
						boardArray[2] = EMPTY_SQUARE; // Empty the king square
						
						//	 get the rook
						movingPiece = getPieceFromArray(boardArray[3], attackers);
						movingPiece.piece_location = 0;   // set rook to castled location
						boardArray[0] = boardArray[3];   // move the array index value over
						boardArray[3] = EMPTY_SQUARE; // Empty the rook square
					}
					if (move.pieceMoving == BLACK_KING) // Black king castles lon
					{
						blackCastleStatus = false;
						// 	get the king
						movingPiece = getPieceFromArray(boardArray[114], attackers);
						movingPiece.piece_location = 116;   // set king to castled location
						boardArray[116] = boardArray[114];   // move the array index value over
						boardArray[114] = EMPTY_SQUARE; // Empty the king square
						
						//	 get the rook
						movingPiece = getPieceFromArray(boardArray[115], attackers);
						movingPiece.piece_location = 112;   // set rook to castled location
						boardArray[112] = boardArray[115];   // move the array index value over
						boardArray[115] = EMPTY_SQUARE; // Empty the rook square
					}		
					break; // Done with unmake
				}
			case EN_PASSANT:
				{
					movingPiece = getPieceFromArray(boardArray[move.toIndex], attackers);
					movingPiece.piece_location = move.fromIndex;
					boardArray[move.fromIndex] = boardArray[move.toIndex];
					boardArray[move.toIndex] = EMPTY_SQUARE; // Clear the original square

					// Put back a black pawn on the right square if white moving
					if(move.pieceMoving == WHITE_PAWN){
						
						capturedPiece = getPieceFromArray(move.capturedPieceIndex, blackPieces);
						capturedPiece.piece_location = move.toIndex-16;
						
						boardArray[move.toIndex - 16] = move.capturedPieceIndex;
					}
					// If it wasn't a white pawn, it's a black pawn and we put a white pawn on
					// the right square
					else {
						capturedPiece = getPieceFromArray(move.capturedPieceIndex, whitePieces);
						capturedPiece.piece_location = move.toIndex+16;
						boardArray[move.toIndex + 16] = move.capturedPieceIndex;				
					}

					break;
				}
			// This catches both ordinary moves and promotions (since the piece moving will
			// be a pawn no matter what it turned in to at promotion)
			default:
				{
					movingPiece = getPieceFromArray(boardArray[move.toIndex], attackers);
					boardArray[move.fromIndex] = boardArray[move.toIndex];
					if (move.capturedPieceIndex != NO_CAPTURE){
						capturedPiece = getPieceFromArray(move.capturedPieceIndex, defenders);
						capturedPiece.piece_location = move.toIndex;
						boardArray[move.toIndex] = move.capturedPieceIndex;
					}
											
					movingPiece.piece_location = move.fromIndex;
					
					 // Put back the piece
					 // Capture holds the value for
					// case PROMOTION_QUEEN: 
					if (move.capturedPieceIndex == NO_CAPTURE){
						boardArray[move.toIndex] = EMPTY_SQUARE;
					}
					
					if(move.moveType == PROMOTION_QUEEN || move.moveType == PROMOTION_ROOK || move.moveType == PROMOTION_BISHOP || move.moveType == PROMOTION_KNIGHT){
							movingPiece.piece_type=toMove*WHITE_PAWN;
							
					}
				}				
		}
		
		loc = ((Piece)blackPieces.get(0)).piece_location;
		
		
		//LOG.debug("After unmake:  " + getFEN());

	}
	// END unmakeMove()

	/**
	 *  Returns a FEN-string without half-moves and full moves count
	 *
	 *  @return String Shorted FEN
	 */
	public String getShortFEN()
	{
	String fen_string = ""; // This holds the FEN-string

		// ***
		// The following lines adds the pieces and empty squares to the FEN
		// ***

		int index = 112; // Keeps track of the index on the board
		int empties = 0; // Number of empty squares in a row

		while (index >= 0) // Run until end of the real board
		{
			if((index & 0x88) != 0) // Reached the end of a rank
			{
				if(empties != 0)
				{
					fen_string += empties; // Add the empties number if it's not 0
					empties = 0;
				}
				index -= 24; // Jump to the next rank
				if(index >= 0) fen_string += "/"; // Add to mark a new rank, if we're not at the end
			}	      
			else // The index is on the real board
			{
				if(boardArray[index] != EMPTY_SQUARE) // If a piece is on the square
					// i.e. the square it not empty
				{
					if(empties != 0) fen_string += empties; // Add the empty square number
					// if it's not 0
					empties = 0; // Reset empties (since we now have a piece coming)
				}

				switch(boardArray[index])
				{
					// Add the piece on the square
					case WHITE_KING: fen_string += "K";	break;
					case WHITE_QUEEN: fen_string += "Q"; break;
					case WHITE_ROOK: fen_string += "R";	break;
					case WHITE_BISHOP: fen_string += "B"; break;
					case WHITE_KNIGHT: fen_string += "N"; break;
					case WHITE_PAWN: fen_string += "P"; break;
					case BLACK_KING: fen_string += "k";	break;
					case BLACK_QUEEN: fen_string += "q"; break;
					case BLACK_ROOK: fen_string += "r"; break;
					case BLACK_BISHOP: fen_string += "b"; break;
					case BLACK_KNIGHT: fen_string += "n"; break;
					case BLACK_PAWN: fen_string += "p";	break;
					default: empties++; // If no piece, increment the empty square count
				}
				index++; // Go to the next square
			}


		}

		// END Adding pieces
		
		fen_string += " "; // Add space for next part

		// Adds side to move (important space before the letter here)
		if(toMove == WHITE_TO_MOVE) fen_string += "w"; // White's move
		else fen_string += "b"; // Black's move

		fen_string += " "; // Add space for next part

		// Castling rights
		if(white_castle == CASTLE_NONE && black_castle == CASTLE_NONE) fen_string += "-"; // Neither
		else // Atleast one side can castle one way
		{
			switch(white_castle) // Check white's castling rights
			{
				case CASTLE_SHORT: fen_string += "K"; break;
				case CASTLE_LONG: fen_string += "Q"; break;
				case CASTLE_BOTH: fen_string += "KQ"; break;
			}

			switch(black_castle) // Check black's castling rights
			{
				case CASTLE_SHORT: fen_string += "k"; break;
				case CASTLE_LONG: fen_string += "q"; break;
				case CASTLE_BOTH: fen_string += "kq"; break;
			}
		}

		fen_string += " "; // Add space for next part

		// En passant square
		
		if(enPassant == -1) fen_string += "-"; // If no en passant is available
		else // An en passant is available
		{
			switch(enPassant%16) // Find the row
			{
				case 0: fen_string += "a"; break;
				case 1: fen_string += "b"; break;
				case 2: fen_string += "c"; break;
				case 3: fen_string += "d"; break;
				case 4: fen_string += "e"; break;
				case 5: fen_string += "f"; break;
				case 6: fen_string += "g"; break;
				case 7: fen_string += "h"; break;
				default: fen_string += "Error in ep square";
			}
			switch((enPassant-(enPassant%16))/16) // Find the rank
			{
				case 2: fen_string += "3"; break;
				case 5: fen_string += "6"; break;
				default: fen_string += "Error in ep square"; // Since en passants only can occur
					 				     // on 3rd and 6th rank, any other
									     // rank is an error
			}
		}

		return fen_string; // Returns the finished FEN-string
	}
	// END getShortFEN()

	/**
	 *  Returns the current position in FEN-notation
	 *
	 *  @return A string with FEN-notation
	 */
	public String getFEN()
	{
		
		Piece piece = null;
		Vector 	pieces = blackPieces;  // initialized to black pieces but it is quickly overriden
		
		String fen_string = ""; // This holds the FEN-string

		// ***
		// The following lines adds the pieces and empty squares to the FEN
		// ***

		int index = 112; // Keeps track of the index on the board
		int empties = 0; // Number of empty squares in a row

		while (index >= 0) // Run until end of the real board
		{
			
			if((index & 0x88) != 0) // Reached the end of a rank
			{	
				if(empties != 0)
				{
					fen_string += empties; // Add the empties number if it's not 0
					empties = 0;
				}
				index -= 24; // Jump to the next rank
				if(index >= 0) fen_string += "/"; // Add to mark a new rank, if we're not at the end
			}	      
			else // The index is on the real board
			{
				
				if(boardArray[index] != EMPTY_SQUARE) // If a piece is on the square
					// i.e. the square it not empty
				{
					
					if(empties != 0) fen_string += empties; // Add the empty square number
					// if it's not 0
					empties = 0; // Reset empties (since we now have a piece coming)
					
					if (boardArray[index] < 0){
						pieces = blackPieces;
					}
					else{
						pieces = whitePieces;
					}
				}
				piece = getPieceFromArray(boardArray[index], pieces);
				
				switch(piece.piece_type)
				{
					// Add the piece on the square
					case WHITE_KING: fen_string += "K";	break;
					case WHITE_QUEEN: fen_string += "Q"; break;
					case WHITE_ROOK: fen_string += "R";	break;
					case WHITE_BISHOP: fen_string += "B"; break;
					case WHITE_KNIGHT: fen_string += "N"; break;
					case WHITE_PAWN: fen_string += "P"; break;
					case BLACK_KING: fen_string += "k";	break;
					case BLACK_QUEEN: fen_string += "q"; break;
					case BLACK_ROOK: fen_string += "r"; break;
					case BLACK_BISHOP: fen_string += "b"; break;
					case BLACK_KNIGHT: fen_string += "n"; break;
					case BLACK_PAWN: fen_string += "p";	break;
					default: empties++; // If no piece, increment the empty square count
				}
				index++; // Go to the next square
			}


		}

		// END Adding pieces
		
		fen_string += " "; // Add space for next part

		// Adds side to move (important space before the letter here)
		if(toMove == WHITE_TO_MOVE) fen_string += "w"; // White's move
		else fen_string += "b"; // Black's move

		fen_string += " "; // Add space for next part

		// Castling rights
		if(white_castle == CASTLE_NONE && black_castle == CASTLE_NONE) fen_string += "-"; // Neither
		else // Atleast one side can castle one way
		{
			switch(white_castle) // Check white's castling rights
			{
				case CASTLE_SHORT: fen_string += "K"; break;
				case CASTLE_LONG: fen_string += "Q"; break;
				case CASTLE_BOTH: fen_string += "KQ"; break;
			}

			switch(black_castle) // Check black's castling rights
			{
				case CASTLE_SHORT: fen_string += "k"; break;
				case CASTLE_LONG: fen_string += "q"; break;
				case CASTLE_BOTH: fen_string += "kq"; break;
			}
		}

		fen_string += " "; // Add space for next part

		// En passant square
		
		if(enPassant == -1) fen_string += "-"; // If no en passant is available
		else // An en passant is available
		{
			switch(enPassant%16) // Find the row
			{
				case 0: fen_string += "a"; break;
				case 1: fen_string += "b"; break;
				case 2: fen_string += "c"; break;
				case 3: fen_string += "d"; break;
				case 4: fen_string += "e"; break;
				case 5: fen_string += "f"; break;
				case 6: fen_string += "g"; break;
				case 7: fen_string += "h"; break;
				default: fen_string += "Error in ep square";
			}
			switch((enPassant-(enPassant%16))/16) // Find the rank
			{
				case 2: fen_string += "3"; break;
				case 5: fen_string += "6"; break;
				default: fen_string += "Error in ep square"; // Since en passants only can occur
					 				     // on 3rd and 6th rank, any other
									     // rank is an error
			}
		}

		fen_string += " "; // Add space for next part
		fen_string += movesFifty; // Add half-moves since last capture/pawn move
		fen_string += " ";
		fen_string += movesFull; // Add number of full moves in the game so far
		
		return fen_string; // Returns the finished FEN-string
	}
	// END getFEN()

	/**
	 *  Takes a FEN-string and sets the board accordingly
	 *
	 * @param String fen
	 */
	public void inputFEN(String fen)
	{
		
		Piece piece = null;
		
		String trimmedFen = fen.trim(); // Removes any white spaces in front or behind the string
		boardArray = new int[128]; // Empties the board from any pieces
		
		// initialize the piece vectors
		whitePieces = new Vector();
		blackPieces = new Vector();
		
		//  add a dummy piece to each to take up the 0 slot
		whitePieces.add(new Piece());
		blackPieces.add(new Piece());
		
		String currentChar; // Holds the current character in the fen

		int i = 0; // Used to go through the fen-string character by character

		int boardIndex = 112; // Keeps track of current index on the board (while adding pieces)
				      // Starts at "a8" (index 112) since the fen string starts on this square

		int currentStep = 0; // This will be incremented when a space is detected in the string
				     // 0 - Pieces
				     // 1 - Side to move
				     // 2 - Castling rights
				     // 3 - En passant square
				     // 4 - Half-moves (for 50 move rule) and full moves

		white_castle = CASTLE_NONE; // Resetting, will be changed below if castling rights are found
		black_castle = CASTLE_NONE;
		boolean fenFinished = false; // Set to true when we're at the end of the fen-string
		while(!fenFinished && i < trimmedFen.length())
		{
			currentChar = trimmedFen.substring(i,i+1); // Gets the current character from the fen-string

			// If a space is detected, get the next character, and move to next step
			if(currentChar.equals(" ")) 
			{
				i++;
				currentChar = trimmedFen.substring(i,i+1);
				currentStep++;
			}


			switch(currentStep) // Determine what step we're on
			{
				case 0: // Pieces
				{
					switch(currentChar.charAt(0)) // See what piece is on the square
					{
						// If character is a '/' move to first row on next rank
						case '/': boardIndex -= 24; break;

						// If the character is a piece, add it and move to next square
						case 'K': 
							piece = new Piece();
							piece.piece_type = WHITE_KING;
							piece.piece_location = boardIndex;
							whitePieces.add(piece);
							boardArray[boardIndex] = whitePieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'Q':  
							piece = new Piece();
							piece.piece_type = WHITE_QUEEN;
							piece.piece_location = boardIndex;
							whitePieces.add(piece);
							boardArray[boardIndex] = whitePieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'R':  
							piece = new Piece();
							piece.piece_type = WHITE_ROOK;
							piece.piece_location = boardIndex;
							whitePieces.add(piece);
							boardArray[boardIndex] = whitePieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'B':  
							piece = new Piece();
							piece.piece_type = WHITE_BISHOP;
							piece.piece_location = boardIndex;
							whitePieces.add(piece);
							boardArray[boardIndex] = whitePieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'N':  
							piece = new Piece();
							piece.piece_type = WHITE_KNIGHT;
							piece.piece_location = boardIndex;
							whitePieces.add(piece);
							boardArray[boardIndex] = whitePieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'P':  
							piece = new Piece();
							piece.piece_type = WHITE_PAWN;
							piece.piece_location = boardIndex;
							whitePieces.add(piece);
							boardArray[boardIndex] = whitePieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'k':  
							piece = new Piece();
							piece.piece_type = BLACK_KING;
							piece.piece_location = boardIndex;
							blackPieces.add(piece);
							boardArray[boardIndex] = -blackPieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'q':  
							piece = new Piece();
							piece.piece_type = BLACK_QUEEN;
							piece.piece_location = boardIndex;
							blackPieces.add(piece);
							boardArray[boardIndex] = -blackPieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'r':  
							piece = new Piece();
							piece.piece_type = BLACK_ROOK;
							piece.piece_location = boardIndex;
							blackPieces.add(piece);
							boardArray[boardIndex] = -blackPieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'b':  
							piece = new Piece();
							piece.piece_type = BLACK_BISHOP;
							piece.piece_location = boardIndex;
							blackPieces.add(piece);
							boardArray[boardIndex] = -blackPieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'n':  
							piece = new Piece();
							piece.piece_type = BLACK_KNIGHT;
							piece.piece_location = boardIndex;
							blackPieces.add(piece);
							boardArray[boardIndex] = -blackPieces.indexOf(piece); 
							boardIndex++; 
							break;
						case 'p':  
							piece = new Piece();
							piece.piece_type = BLACK_PAWN;
							piece.piece_location = boardIndex;
							blackPieces.add(piece);
							boardArray[boardIndex] = -blackPieces.indexOf(piece); 
							boardIndex++; 
							break;

						// If no piece was found, it has to be a number of empty squares
						// so move to that board index
						default: boardIndex += Integer.parseInt(currentChar);
					}
				}
				case 1: // Side to move
				{
					if(currentChar.equals("w")) toMove = WHITE_TO_MOVE;
					else toMove = BLACK_TO_MOVE;
					break;
				}
				case 2: // Castling rights
				{
					// '-' states that no castling is available so we simply keep the values
					// we set before the while-loop, and don't need to do anything here.
					switch(currentChar.charAt(0))
					{
						// White can atleast castle short
						case 'K': white_castle = CASTLE_SHORT; break;

						case 'Q': // White can atleast castle long
						{
							// If white already can castle short, do both, else only long
							if(white_castle == CASTLE_SHORT) white_castle = CASTLE_BOTH;
							else white_castle = CASTLE_LONG;
							break;
						}
						// Black can atleast castle short
						case 'k': black_castle = CASTLE_SHORT; break;

						case 'q': // Black can atleast castle long
						{
							// If black already can castle short, do both, else only long
							if(black_castle == CASTLE_SHORT) black_castle = CASTLE_BOTH;
							else black_castle = CASTLE_LONG;
							break;
						}
					}
					break;					
				}
				case 3: // En passant
				{
					if(currentChar.equals("-")) enPassant = -1;
					else
					{
						switch(currentChar.charAt(0)) // Find the row
						{
							case 'a': enPassant = 0; break;
							case 'b': enPassant = 1; break;
							case 'c': enPassant = 2; break;
							case 'd': enPassant = 3; break;
							case 'e': enPassant = 4; break;
							case 'f': enPassant = 5; break;
							case 'g': enPassant = 6; break;
							case 'h': enPassant = 7; break;
						}
						// Get the next character (the rank)
						i++;
						currentChar = trimmedFen.substring(i,i+1);

						// On rank 3 or else rank 6
						if(currentChar.equals("3")) enPassant += 32; // Add 2 ranks to index
						else enPassant += 80; // Add 5 ranks to index
					}
					break;
				}
				case 4: // Half-moves (50 move rule) and full moves
				{
					// If the next character is a space, we're done with half-moves and
					// can insert them
					if(trimmedFen.substring(i+1,i+2).equals(" "))
					{
						movesFifty = Integer.parseInt(currentChar);
					}
					// If the next character is not a space, we know it's a number
					// and since half-moves can't be higher than 50 (or it can, but the game
					// is drawn so there's not much point to it), we can assume
					// there are two numbers and then we're done with half-moves.
					else
					{
						movesFifty = Integer.parseInt(trimmedFen.substring(i,i+2));
						i++;
					}
					i += 2;
					movesFull = Integer.parseInt(trimmedFen.substring(i));
					fenFinished = true; // We're done with the fen-string and can exit the loop
					break;
				}
			}
			i++; // Move to the next character in the fen-string
		}		
	}
	// END inputFEN()
	/*****************************/
	/** Move generation methods **/
	/*****************************/
	
	/**
	 *  Returns a Vector with legal Moves
	 *
	 *  @return Vector All legal Moves on the board
	 */
	public Vector generateMoves(boolean onlyCaptures)
	{
		LOG.debug("Entering generateMoves");
		
		Monitor mon=null;	
		mon = MonitorFactory.start("generatePseudoMoves");
			Vector pseudoMoves = generatePseudoMoves(onlyCaptures);
		mon.stop();
		//LOG.info(mon.toString());
		
		mon = MonitorFactory.start("filterMoves");
		Vector legalMoves = filterMoves(pseudoMoves);
		mon.stop();
		//LOG.info(mon.toString());
		
		LOG.debug("Exiting generateMoves");
		return legalMoves;
	}
	// END getLegalMoves()
	
	/**
	 *  Takes a vector with pseudo-legal moves and filters out the illegal ones
	 *  returning a vector with legal moves
	 *
	 *  @param Vector The pseudo-legal moves
	 *  @return Vector The legal moves left
	 */
	private Vector filterMoves(Vector pseudoMoves)
	{
		
		LOG.debug("Entering filterMoves");
		
		
		
		Vector filteredMoves = new Vector();
		Vector attackers = getAttackingPieces();
		Piece currentPiece = null;
		Iterator it = attackers.iterator();
		
		// Start with finding the king on the board
		int king_square = -1;		
		
		
		while (it.hasNext()){
			currentPiece = (Piece)it.next();
			if (currentPiece.piece_type * toMove == WHITE_KING)
				king_square = currentPiece.piece_location;
		}
		

		
		if(king_square == -1) return pseudoMoves; // No king was found, so we can't filter

		// 
		// Now go through every move
		for(int i = 0; i < pseudoMoves.size(); i++)
		{
			
		
			Move currentMove = (Move)pseudoMoves.get(i); // Get a move from the vector
			
			
			// If the move is a castle we also need to check for castling in check
			// and over attacked squares, so check the type of move
			switch(currentMove.moveType)
			{
				case SHORT_CASTLE:
				{
		
					makeMove(currentMove); // Make the move on the board
		
					
					// Now check if the king's original square or the two to the right
					// are attacked.
					// This catches all three posibilities; castle in check, castle over
					// attacked square and castle into check.
					//
					// If neither is attacked we can add it to legal moves.
					if(!isAttacked(currentMove.fromIndex)     &&
					   !isAttacked(currentMove.fromIndex + 1) &&
					   !isAttacked(currentMove.fromIndex + 2)){
							
							filteredMoves.add(currentMove);
												
					}
						
					
					unmakeMove(currentMove); // Unmake the move to reset the board
					currentMove.updateScore(this);  // this will add a score value to the move
					break;
				}
				case LONG_CASTLE:
				{
		
					makeMove(currentMove); // Make the move on the board
		
					// Now check if the king's original square or the two to the left
					// are attacked.
					// This catches all three posibilities; castle in check, castle over
					// attacked square and castle into check.
					//
					// If neither is attacked we can add it to legal moves.
					if(!isAttacked(currentMove.fromIndex)     &&
					   !isAttacked(currentMove.fromIndex - 1) &&
					   !isAttacked(currentMove.fromIndex - 2)){
						
						filteredMoves.add(currentMove);
						
					}
					
					unmakeMove(currentMove); // Unmake the move to reset the board
					currentMove.updateScore(this);  // this will add a score value to the move
					break;
				}				

				default: // Catches all other types of moves
				{
		
					makeMove(currentMove); // Make the move on the board
		

					// We have already determined the king square, but if the king
					// is moving we need to call isAttacked with its new square
					// and not where it stood before
					if(currentMove.pieceMoving == WHITE_KING || currentMove.pieceMoving == BLACK_KING)
					{
						if(!isAttacked(currentMove.toIndex)){
							
							filteredMoves.add(currentMove);
							
						}
					}
					// If it's not the king moving, we use where it's standing as
					// determined before
					else
					{
						
						// If the king can't be attacked add the move
						if(!isAttacked(king_square)){
							
							//LOG.debug("added legal move: " + currentMove.inputNotation());
							filteredMoves.add(currentMove);
							
						}
						
						
					}

					
					unmakeMove(currentMove); // Unmake the move to reset the board
					currentMove.updateScore(this);  // this will add a score value to the move
				}
			}
		}
		
		//LOG.debug("filteredmoves size= " + filteredMoves.size());	
		
		
		return filteredMoves; // We are now done and can return the filtered moves
	}
	// END filterMoves()
	
	/**
	 *  Returns a vector with pseduo-legal moves
	 *
	 * @return Vector All pseudo-legal Moves on the board
	 */
	private Vector generatePseudoMoves(boolean onlyCaptures)
	{
		LOG.debug("Entering generatePseudoMoves");
		
		Vector pseudoMoves = new Vector();
		Piece piece = null;
		
		
		
		// we will cycle through the piece array of the side who is to move
		Vector attackers = getAttackingPieces(); 
		
		Iterator i = attackers.iterator();
		
		while (i.hasNext()){
			
			piece = (Piece)i.next();
			
			//  only act on pieces who are still on the board (e.g. location is not EMPTY_SQUARE)
			if (piece.piece_location != OFF_BOARD){  // captured pieces have a location of -1

				
				switch(piece.piece_type) 
				{
					case EMPTY_SQUARE: break; // Do nothing on empty squares
				
					case WHITE_QUEEN:
					case BLACK_QUEEN:
						pseudoMoves = genMoves(piece.piece_location, queen_delta, true, pseudoMoves, onlyCaptures); break;
						
					case WHITE_ROOK: 
					case BLACK_ROOK:
						pseudoMoves = genMoves(piece.piece_location, rook_delta, true, pseudoMoves, onlyCaptures); break;
						
					case WHITE_BISHOP: 
					case BLACK_BISHOP:
						pseudoMoves = genMoves(piece.piece_location, bishop_delta, true, pseudoMoves, onlyCaptures); break;
						
					case WHITE_KNIGHT: 
					case BLACK_KNIGHT:	
						pseudoMoves = genMoves(piece.piece_location, knight_delta, false, pseudoMoves, onlyCaptures); break;
						
					case WHITE_KING:
					case BLACK_KING:
						       {
							       pseudoMoves = genMoves(piece.piece_location, king_delta, false, pseudoMoves, onlyCaptures);
							       if(onlyCaptures==false)
							    	   pseudoMoves = genCastling(pseudoMoves);
							       break; 
						       }
						       
					case WHITE_PAWN:
					case BLACK_PAWN:
						
						pseudoMoves = genPawn(piece.piece_location, pseudoMoves, onlyCaptures); break;
				}				
			}
			
		}
		LOG.debug("Exiting generatePseudoMoves");
		return pseudoMoves;
	}
	private Vector getAttackingPieces() {

		// this method simply returns the pieces of the side to move
		
		if (toMove == WHITE_TO_MOVE)
			return whitePieces;
		else
			return blackPieces;
		
		
	}
	// END generatePseudoMoves()
	
	/**
	 *  Adds all possible moves for the pawn
	 *
	 *  @param int Index the piece is on 
	 *  @param Vector The pseudoMoves vector to be filled
	 *  @return Vector The updates pseudoMoves
	 */
	private Vector genPawn(int index, Vector pseudoMoves, boolean onlyCaptures)
	{
		
		LOG.debug("Entering genPawn");
		
		
		// Record the board's en passant square, white/black castling rights and half-moves
		int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};		

		if(toMove == WHITE_TO_MOVE)
		{
			
			if(boardArray[(index + 16)] == EMPTY_SQUARE)// If next square is empty we can move there
			{
				if((index-(index%16))/16 != 6) // If the pawn is not on 7th rank
				{
					// Add ordinary pawn move
					if(onlyCaptures==false)
						pseudoMoves.add(new Move(WHITE_PAWN,index,index + 16,0,NORMAL_MOVE,prevPos));
				}
				else if(onlyCaptures==false) // Add promotion if on 7th rank if we are getting non-captures
				{
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 16,0,PROMOTION_QUEEN,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 16,0,PROMOTION_ROOK,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 16,0,PROMOTION_BISHOP,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 16,0,PROMOTION_KNIGHT,prevPos));
				}
			}


			// If next square diagonally left contains a opposite side piece,
			// it's possible to capture
			if(((index + 15) & 0x88) == 0 && boardArray[(index + 15)] < 0)
			{
				if((index-(index%16))/16 != 6) // If not on 7th rank
				{	
					// Add ordinary pawn move			
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 15,boardArray[(index + 15)],NORMAL_MOVE,prevPos));
				}
				else // Add promotion if on 7th rank
				{

					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 15,boardArray[(index + 15)],PROMOTION_QUEEN,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 15,boardArray[(index + 15)],PROMOTION_ROOK,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 15,boardArray[(index + 15)],PROMOTION_BISHOP,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 15,boardArray[(index + 15)],PROMOTION_KNIGHT,prevPos));
				}
			}
			// If next square diagonally right contains a opposite side piece,
			// it's possible to capture
			if(((index + 17) & 0x88) == 0 && boardArray[(index + 17)] < 0)
			{
				if((index-(index%16))/16 != 6) // If not on 7th rank
				{
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 17,boardArray[(index + 17)],NORMAL_MOVE,prevPos));
				}
				else
				{				
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 17,boardArray[(index + 17)],PROMOTION_QUEEN,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 17,boardArray[(index + 17)],PROMOTION_ROOK,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 17,boardArray[(index + 17)],PROMOTION_BISHOP,prevPos));
					pseudoMoves.add(new Move(WHITE_PAWN,index,index + 17,boardArray[(index + 17)],PROMOTION_KNIGHT,prevPos));
				}
			}	
			// If the pawn is standing on its original square (rank 2)
			// it is possible to move two squares if both squares in front of it are empty
			if(((index-(index%16))/16 == 1) && (boardArray[(index + 16)] == EMPTY_SQUARE) && (boardArray[(index + 32)] == EMPTY_SQUARE))
				if(onlyCaptures == false)
					pseudoMoves.add(new Move(WHITE_PAWN, index, index + 32,0,NORMAL_MOVE,prevPos));

			// If there is an en passant square and the pawn can reach it
			// we can add en passant
			if(enPassant != -1 && ((index + 17) == enPassant) || ((index + 15) == enPassant))
				pseudoMoves.add(new Move(WHITE_PAWN, index,enPassant,BLACK_PAWN,EN_PASSANT,prevPos));



		}

		else // Black's move
		{
			//LOG.debug("Pawn is on square:  " + index);
			if(boardArray[(index - 16)] == EMPTY_SQUARE)// If next square is empty we can move there
			{
				
				if((index-(index%16))/16 != 1) // If the pawn is not on 2nd rank
				{
					// Add ordinary pawn move
					if(onlyCaptures==false)
						pseudoMoves.add(new Move(BLACK_PAWN,index,index - 16,0,NORMAL_MOVE,prevPos));
				}
				else if(onlyCaptures==false)// Add promotion if on 7th rank
				{
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 16,0,PROMOTION_QUEEN,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 16,0,PROMOTION_ROOK,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 16,0,PROMOTION_BISHOP,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 16,0,PROMOTION_KNIGHT,prevPos));
				}
			}


			// If next square diagonally left contains a opposite side piece,
			// it's possible to capture
			if(((index - 15) & 0x88) == 0 && boardArray[(index - 15)] > 0)
			{
				if((index-(index%16))/16 != 1) // If not on 2nd rank
				{	
					// Add ordinary pawn move			
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 15,boardArray[(index - 15)],NORMAL_MOVE,prevPos));
				}
				else // Add promotion if on 2nd rank
				{

					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 15,boardArray[(index - 15)],PROMOTION_QUEEN,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 15,boardArray[(index - 15)],PROMOTION_ROOK,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 15,boardArray[(index - 15)],PROMOTION_BISHOP,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 15,boardArray[(index - 15)],PROMOTION_KNIGHT,prevPos));
				}
			}
			// If next square diagonally right contains a opposite side piece,
			// it's possible to capture
			if(((index - 17) & 0x88) == 0 && boardArray[(index - 17)] > 0)
			{
				if((index-(index%16))/16 != 1) // If not on 2nd rank
				{
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 17,boardArray[(index - 17)],NORMAL_MOVE,prevPos));
				}
				else
				{				
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 17,boardArray[(index - 17)],PROMOTION_QUEEN,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 17,boardArray[(index - 17)],PROMOTION_ROOK,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 17,boardArray[(index - 17)],PROMOTION_BISHOP,prevPos));
					pseudoMoves.add(new Move(BLACK_PAWN,index,index - 17,boardArray[(index - 17)],PROMOTION_KNIGHT,prevPos));
				}
			}	
			// If the pawn is standing on its original square (rank 7)
			// it is possible to move two squares if both squares in front of it are empty
			if(((index-(index%16))/16 == 6) && (boardArray[(index - 16)] == EMPTY_SQUARE) && (boardArray[(index - 32)] == EMPTY_SQUARE))
				if(onlyCaptures == false)
					pseudoMoves.add(new Move(BLACK_PAWN, index, index - 32,0,NORMAL_MOVE,prevPos));

			// If there is an en passant square and the pawn can reach it
			// we can add en passant
			if(enPassant !=-1 && ((index - 17) == enPassant) || ((index - 15) == enPassant))
				pseudoMoves.add(new Move(BLACK_PAWN, index,enPassant,WHITE_PAWN,EN_PASSANT,prevPos));
		}
		LOG.debug("Exiting genPawn");
		return pseudoMoves;
	}
	// END genPawn()
	
	
	/**
	 *  Checks if castling is available for the king and adds the move if it
	 *
	 *  @param int The king on the move
	 *  @param Vector The pseudoMoves vector to be filled
	 *  @return Vector The updated pseudoMoves
	 */
	private Vector genCastling(Vector pseudoMoves)
	{
		LOG.debug("Entering genCastling");
		
		if(toMove == WHITE_TO_MOVE) // White king moving
		{
			switch(white_castle)
			{
				case CASTLE_NONE: return pseudoMoves; // No castling
				case CASTLE_SHORT:
				{
					// If squares between king and rook are empty, add short castle
					if((boardArray[5] == EMPTY_SQUARE) && (boardArray[6] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(WHITE_KING,4,6,0,SHORT_CASTLE,prevPos));
					}
					break;
				}
				case CASTLE_LONG:
				{
					// If squares between king and rook are empty, add long castle
					if((boardArray[1] == EMPTY_SQUARE) && (boardArray[2] == EMPTY_SQUARE) && (boardArray[3] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(WHITE_KING,4,2,0,LONG_CASTLE,prevPos));
					}
					break;
				}
				default: // Can castle both ways
				{
					
					// If squares between king and rook are empty, add short castle
					if((boardArray[5] == EMPTY_SQUARE) && (boardArray[6] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(WHITE_KING,4,6,0,SHORT_CASTLE,prevPos));
					}
					// If squares between king and rook are empty, add long castle
					if((boardArray[1] == EMPTY_SQUARE) && (boardArray[2] == EMPTY_SQUARE) && (boardArray[3] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(WHITE_KING,4,2,0,LONG_CASTLE,prevPos));
					}					
				}
			}
		}
		else // Black king moving
		{
			switch(black_castle)
			{
				case CASTLE_NONE: return pseudoMoves; // No castling
				case CASTLE_SHORT:
				{
					// If squares between king and rook are empty, add short castle
					if((boardArray[117] == EMPTY_SQUARE) && (boardArray[118] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(BLACK_KING,116,118,0,SHORT_CASTLE,prevPos));
					}
					break;
				}
				case CASTLE_LONG:
				{
					// If squares between king and rook are empty, add long castle
					if((boardArray[115] == EMPTY_SQUARE) && (boardArray[114] == EMPTY_SQUARE) && (boardArray[113] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(BLACK_KING,116,114,0,LONG_CASTLE,prevPos));
					}
					break;
				}
				default: // Can castle both ways
				{
					// If squares between king and rook are empty, add short castle
					if((boardArray[117] == EMPTY_SQUARE) && (boardArray[118] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(BLACK_KING,116,118,0,SHORT_CASTLE,prevPos));
					}
					// If squares between king and rook are empty, add long castle
					if((boardArray[115] == EMPTY_SQUARE) && (boardArray[114] == EMPTY_SQUARE) && (boardArray[113] == EMPTY_SQUARE))
					{
						int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
						pseudoMoves.add(new Move(BLACK_KING,116,114,0,LONG_CASTLE,prevPos));
					}				
				}
			}			
		}
		LOG.debug("Exiting genCastling");
		return pseudoMoves; // Done with castling generation
	}
	// END genCastling()

	/**
	 *  Takes an index, a delta, sliding/non-sliding boolean and the pseudoMoves-vector
	 *  and fills the vector with pseudo-legal moves for the piece
	 *  and then returns it
	 *
	 *  @param int The index the piece is on
	 *  @param int[] The piece's delta
	 *  @param boolean Sliding/non-sliding
	 *  @param Vector The pseudoMoves vector to be filled
	 *  @return Vector The updated pseudoMoves
	 */
	private Vector genMoves(int index, int[] delta, boolean sliding, Vector pseudoMoves, boolean onlyCaptures)
	{
		LOG.debug("Entering genMoves");
		//LOG.debug("index = " + index);
		
		Vector attackers = getAttackingPieces();
		Vector defenders = getDefendingPieces();
		Piece movingPiece = getPieceFromArray(boardArray[index], attackers);
		Piece defendingPiece = null;
		
		// Record the board's en passant square, white/black castling rights and half-moves
		int[] prevPos = {enPassant, white_castle, black_castle, movesFifty};
		
		for(int i = 0; i < 8; i++) // Loop through the 8 possible deltas
		{
			// Get the index of a square one step away from the orignal square by using the current delta
			int deltaIndex = index;
			deltaIndex += delta[i];
			while(delta[i] != 0) // Run the loop if we have a valid delta
			{
				if((deltaIndex & 0x88) == 0) // Target square is on the board
				{
					if(boardArray[deltaIndex] == EMPTY_SQUARE) // The target square is empty
					{
						// Add the move to pseudoMoves if not getting only captures
						if(onlyCaptures == false)
							pseudoMoves.add(new Move(movingPiece.piece_type,index,deltaIndex,0,NORMAL_MOVE,prevPos));

						if(sliding) deltaIndex += delta[i]; // If the moving piece is sliding, add the next square
						else break; // If not sliding, stop calculating this delta
					}
					else // The target square is not empty
					{
						if((boardArray[index] * boardArray[deltaIndex]) < 0) // If the moving piece times the
																			// target piece is < 0. We know the
                                             							     // target piece is of opposite color
						{
							// Add the move as capture to pseudoMoves (i.e. send the piece int as capture)
							defendingPiece = getPieceFromArray(boardArray[deltaIndex], defenders);
							pseudoMoves.add(new Move(movingPiece.piece_type,index,deltaIndex,defendingPiece.piece_type,NORMAL_MOVE,prevPos));
							break; // We can't go further in this direction
						}
						else break; // The target square contains a piece of the same color so no move here or further
					}
				}
				else break; // We've moved off the board, so stop checking this direction
			}
		}
		LOG.debug("Exiting genMoves");
		return pseudoMoves;
	}
	
	private Vector getDefendingPieces() {

		// this method simply returns the pieces of the side defending
		
		if (toMove == BLACK_TO_MOVE)
			return whitePieces;
		else
			return blackPieces;
	}
	
	public Piece getPieceFromArray(int index, Vector attackers) {
		
		Piece piece = null;
		int absoluteIndex = Math.abs(index);
		piece = (Piece) attackers.get(absoluteIndex);
		return piece;
		
	}
	/**
	 *  Takes an index and checks if the index can be attacked by
	 *  any piece of the side moving.
	 *
	 *  @param int The attacked index
	 *  @return boolean True it can be attacked, false it can't
	 */
	public boolean isAttacked(int attacked)
	{
		
		
		Piece piece = null;

		// we need to get the attacking pieces.  The side toMove has been switched so we need to do this manually
		//
		Vector attackers;
		if(toMove == WHITE_TO_MOVE)
			attackers = whitePieces;
		else
			attackers = blackPieces;
		
		
		for(int attacker = 0; attacker < 120; attacker++) // Loop through all squares
		{
			if((attacker & 0x88) == 0) // If we're on the real board
			{
				// Switch the color of the piece on the square and hold it in the variable,
				// this is done for clearer code below.
				//
				// So if black is moving and we find a black queen (-2) we make it a white
				// queen (2) by multiplying by toMove = -1 (black's move). Now we only have to
				// check for 'white' pieces below.
				if((boardArray[attacker]*toMove) <= 0) continue;
				
				piece = getPieceFromArray(boardArray[attacker], attackers);
				int pieceOnSquare = piece.piece_type * toMove;
				
				
				
				switch(ATTACK_ARRAY[attacked-attacker+128])
				{
					case ATTACK_NONE: break; // No piece can attack from here
					case ATTACK_KQR:
					{
						// If the checked square contains any of the pieces that
						// are able to get to the attacked square.
						//
						// Since this is only one square away from the attacked square
						// we can safely conclude that the square is attacked.
						if(pieceOnSquare == WHITE_KING  ||
						   pieceOnSquare == WHITE_QUEEN ||
						   pieceOnSquare == WHITE_ROOK)
							return true;
						break;
					}
					case ATTACK_QR:
					{
						if(pieceOnSquare == WHITE_QUEEN || pieceOnSquare == WHITE_ROOK)
						{
							// If the traverse hits the attacked square
							// the piece can attack it.
							if(traverseDelta(attacker, attacked))
									return true;
						}
						break;						
					}
					case ATTACK_KQBwP:
					{
						if(pieceOnSquare == WHITE_KING  ||
						   pieceOnSquare == WHITE_QUEEN ||
						   pieceOnSquare == WHITE_BISHOP)
							return true;

						// If it's white's turn to move and the piece is a white pawn it
						// can attack the square.
						//
						// We do this distinction so we don't confuse black and white pawns,
						// since they can only move in one direction depending on color.
						if(toMove == WHITE_TO_MOVE && piece.piece_type == WHITE_PAWN)
							return true;
						break;

					}
					case ATTACK_KQBbP:
					{
						if(pieceOnSquare == WHITE_KING  ||
						   pieceOnSquare == WHITE_QUEEN ||
						   pieceOnSquare == WHITE_BISHOP)
							return true;

						// If it's black's turn to move and the piece is a white pawn it
						// can attack the square.
						if(toMove == BLACK_TO_MOVE && piece.piece_type == BLACK_PAWN)
							return true;
						break;						
					}
					case ATTACK_QB:
					{
						if(pieceOnSquare == WHITE_QUEEN || pieceOnSquare == WHITE_BISHOP)
						{
							// If the traverse hits the attacked square
							// the piece can attack it.
							if(traverseDelta(attacker, attacked))
									return true;
						}
						break;
					}
					case ATTACK_N:
					{
						// Knights can jump over pieces so we don't have to
						// check for pieces in the way.
						if(pieceOnSquare == WHITE_KNIGHT)
							return true;
						break;
					}
				}
			}
			else attacker += 7; // Not on board, so move to next rank
					    // +7 since for-loop will add 1 as well
		}

		return false; // If the loop didn't return true, no piece can attack the square
	}
	// END isAttacked()
	
	/**
	 *  Used by isAttacked() to traverse a piece's delta to
	 *  see if it runs in to any pieces on the way to the attacked square
	 *
	 *  @param int The attacking square
	 *  @param int The attacked square
	 *  @return boolean True if the piece can reach the attacked square, false if not
	 */
	private boolean traverseDelta(int attacker, int attacked)
	{
		int deltaIndex = attacker; // Initialize from first square
		int delta = DELTA_ARRAY[attacked - attacker + 128]; // Find the delta needed

		while((deltaIndex & 0x88) == 0) // Traverse until off the board
		{
			deltaIndex += delta; // Add the delta to move to the next square

			// We reached the attacked square, so we return true
			if(deltaIndex == attacked) return true;

			// A piece was found on the way, so return false
			if(boardArray[deltaIndex] != EMPTY_SQUARE) return false;
		}
		return false; // If we for some reason missed the attacked square and wandered off the board
			      // return false. This shouldn't happen.
	}
	// END traverseDelta()


	/*********************************/
	/** End move generation methods **/
	/*********************************/

	
	
}
